﻿using System;
using System.Reflection;
using ORM.Attribute;

namespace ORM
{
    public class AttributeHelper
    {
        /// <summary>
        /// 获取指定的自定义属性对象
        /// </summary>
        /// <typeparam name="T">自定义特性类型</typeparam>
        /// <typeparam name="TK">被添加的类类型</typeparam>
        /// <returns>自定义特性对象</returns>
        private static T GetAttribute<T, TK>() where T : System.Attribute where TK : ITableObject
        {
            string key = typeof(TK).FullName + "_" + typeof(T).FullName;
            object obj = CacheHelper.GetCache(key);
            if (null != obj) return (T) obj;

            T t = System.Attribute.GetCustomAttribute(typeof(TK), typeof (T)) as T;
            CacheHelper.SetCache(key, t);
            return t;
        }
        /// <summary>
        /// 获取TableAttribute特性对象
        /// </summary>
        /// <typeparam name="T">被添加的类类型</typeparam>
        /// <returns>特性对象</returns>
        internal static TableAttribute GetTableAttribute<T>() where T : ITableObject
        {
            return GetAttribute<TableAttribute, T>();
        }

        /// <summary>
        /// 获取表字段
        /// </summary>
        /// <typeparam name="T">表实体类型</typeparam>
        /// <returns>特性对象</returns>
        internal static FieldAttribute GetFieldAttribute<T>() where T : ITableObject
        {
            return GetAttribute<FieldAttribute, T>();
        }

        internal static string[] GetFields<T>() where T : ITableObject
        {
            string key = typeof(T).Name + "_FieldAttribute";
            string key2 = typeof (T).Name + "_PropertyInfo";

            object obj = CacheHelper.GetCache(key);
            if (null != obj) return (string[]) obj;

            obj = CacheHelper.GetCache(key2);
            PropertyInfo[] infos;

            if (null != obj) infos = (PropertyInfo[])obj; 
            else infos = typeof(T).GetProperties();
            object[] objAttribute;
            string[] fieldNames = new string[infos.Length];
            int i = 0;
            foreach (PropertyInfo info in infos)
            {
                objAttribute = info.GetCustomAttributes(typeof(FieldAttribute), false);
                fieldNames[i++] = ((FieldAttribute) objAttribute[0]).FieldName;
            }
            return fieldNames;
        }

        /// <summary>
        /// 获取表名称
        /// </summary>
        /// <typeparam name="T">表实体类型</typeparam>
        /// <returns></returns>
        internal static string GetTableName<T>() where T : ITableObject
        {
            return GetTableAttribute<T>().TableName;
        }

        /// <summary>
        /// 获取表主键(多个用逗号隔开了)
        /// </summary>
        /// <typeparam name="T">表实体类型</typeparam>
        /// <returns>表主键字符串</returns>
        internal static string GetTablePrimaryKey<T>() where T : ITableObject
        {
            return GetTableAttribute<T>().Primarykey;
        }

        /// <summary>
        /// 获取表主键(多个用逗号隔开了)
        /// </summary>
        /// <typeparam name="T">表实体类型</typeparam>
        /// <returns>表主键字符串</returns>
        internal static string GetTableFromDbAlias<T>() where T : ITableObject
        {
            return GetTableAttribute<T>().DbAlias;
        }
        /// <summary>
        /// 获取表说明字符串
        /// </summary>
        /// <typeparam name="T">表实体类型</typeparam>
        /// <returns>表说明字符串</returns>
        internal static string GetTableDescription<T>() where T : ITableObject
        {
            return GetTableAttribute<T>().Description;
        }
        /// <summary>
        /// 获取指定属性的特性声明
        /// </summary>
        /// <param name="propertyInfo">属性</param>
        /// <returns>字段特性</returns>
        internal static FieldAttribute GetPropertyAttribute(PropertyInfo propertyInfo)
        {
            if (null == propertyInfo) return null;
            return (FieldAttribute)(propertyInfo.GetCustomAttributes(typeof (FieldAttribute), false)[0]);
        }

        /// <summary>
        /// 获取指定对象指定属性的值
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="t">指定的对象</param>
        /// <param name="propertyName">对象的属性名称</param>
        /// <returns>对象指定属性的值</returns>
        internal static object GetPropertyValue<T>(T t, string propertyName) where T : ITableObject, new()
        {
            if (String.IsNullOrEmpty(propertyName)) return null;
            PropertyInfo propertyInfo = typeof (T).GetProperty(propertyName);

            if (null == propertyInfo) return null;
            return propertyInfo.GetValue(t, null);
        }
    }
}
